﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Linq.Expressions;

using NHibernate;
using NHibernate.Criterion;

using ProjectBase.Core;

namespace $safeprojectname$
{
    public static partial class DaoExtensions
    {
        #region string Equal
        public static IList<ICriterion> AddEqual(this IList<ICriterion> criteria, Expression<Func<string>> expr, string value)
        {
            if (value.IsNull())
            {
                return criteria;
            }
            MemberExpression body;
            switch (expr.Body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    body = expr.Body as MemberExpression;
                    break;

                default:
                    throw new NotSupportedException(
                        "Provided 'Expression<Func<string>> expr' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }
            criteria.Add(new SimpleExpression(body.Member.Name, value, Const.Equal, false));

            return criteria;
        }
        public static IList<ICriterion> AddEqual<TFilter>(this IList<ICriterion> criteria, TFilter filter
            , Expression<Func<TFilter, string>> expr)
            where TFilter : Core.IFilter
        {
            MemberExpression body;
            switch (expr.Body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    body = expr.Body as MemberExpression;
                    break;

                default:
                    throw new NotSupportedException(
                        "Provided 'Expression<Func<TFilter, string>> expr' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }

            var name = body.Member.Name;
            if (name.EndsWith("Exact"))
            {
                name = name.Remove((name.Length - 5));
            }

            var result = GetCompiled(expr);
            try
            // there must be try for some cases, for instance when the Nested property object is null e.g. entity.Parent.Code
            {
                var value = result(filter);
                // could result in NullReferenceException if the Parent is null (entity.Parent.Code)
                if (value.Is())
                {
                    criteria.Add(new SimpleExpression(name, value, Const.Equal, false));
                }
            }
            catch (NullReferenceException)
            {
                // entity.Parent.Code -> where Parent is null
            }

            return criteria;
        }
        #endregion string Equal
        
        #region string Like
        public static IList<ICriterion> AddLike(this IList<ICriterion> criteria, Expression<Func<string>> expr, string value)
        {
            if (value.IsNull())
            {
                return criteria;
            }
            MemberExpression body;
            switch (expr.Body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    body = expr.Body as MemberExpression;
                    break;

                default:
                    throw new NotSupportedException(
                        "Provided 'Expression<Func<string>> expr' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }
            return criteria.AddLike(body.Member.Name, value);
        }

        public static IList<ICriterion> AddLike<TFilter>(this IList<ICriterion> criteria, TFilter filter
            , Expression<Func<TFilter, string>> expr)
            where TFilter : Core.IFilter
        {
            MemberExpression body;
            switch (expr.Body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    body = expr.Body as MemberExpression;
                    break;

                default:
                    throw new NotSupportedException(
                        "Provided 'Expression<Func<TFilter, string>> expr' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }

            var result = GetCompiled(expr);
            try
            // there must be try for some cases, for instance when the Nested property object is null e.g. entity.Parent.Code
            {
                var value = result(filter);
                // could result in NullReferenceException if the Parent is null (entity.Parent.Code)
                criteria.AddLike(body.Member.Name, value);
            }
            catch (NullReferenceException)
            {
                // entity.Parent.Code -> where Parent is null
            }
            return criteria;
        }
        #endregion string Like

        #region string NOT Like
        public static IList<ICriterion> AddNotLike(this IList<ICriterion> criteria, Expression<Func<string>> expr, string value)
        {
            MemberExpression body;
            switch (expr.Body.NodeType)
            {
                case ExpressionType.MemberAccess:
                    body = expr.Body as MemberExpression;
                    break;

                default:
                    throw new NotSupportedException(
                        "Provided 'Expression<Func<string>> expr' parameter must be of a 'ExpressionType.MemberAccess'. ");
            }


            criteria.AddNotLike(body.Member.Name, value);


            return criteria;
        }
        #endregion string NOT Like
    }
}